home *** CD-ROM | disk | FTP | other *** search
/ World of Education / World of Education.iso / world_d / drfinfo.zip / CMOS11.ZIP / CMOS.ASM < prev    next >
Assembly Source File  |  1991-09-18  |  18KB  |  724 lines

  1. NAME    CMOSSAVE
  2.     TITLE    CMOSSave Save CMOS to a file on disk or floppy
  3. Comment |
  4.     Version 1.1 1991 Sept 07 Roedy Green
  5.     works with MASM 6.0 and Optasm
  6.  
  7. See CMOS.TXT for details on use.
  8.  
  9.   USAGE:
  10.  
  11. Examples:
  12. *********
  13.  
  14. CMOSSave A:\MyCMOS.Sav
  15.  
  16. CMOSRest A:\MyCMOS.Sav
  17.  
  18. CMOSChk  A:\ByCMOS.Sav
  19.  
  20. Syntax errors or missing file trouble generates an ERRORLEVEL 4.
  21. CMOSChk generates an ERRORLEVEL 1 if the CMOS has changed since
  22. the CMOSSave was done.
  23.  
  24. Version History
  25. ***************
  26.  
  27. Version 1.0
  28. - released to BIX 91/09/07
  29.  
  30. Version 1.1
  31. - released to BIX 91/09/18
  32. - added special check for small 64 character CMOSes.
  33.  
  34. Version 1.2
  35. - not yet written
  36. - add CMOSStuff, like CMOSRest, but computes a valid checksum for you
  37.   it might even have a hex edit and a line of description for each byte.
  38.  
  39. CMOS Usage
  40. **********
  41.  
  42.  2) CMOS RAM map, PC/AT:
  43.     offset        contents
  44.     00h     Seconds
  45.     01h     Second Alarm
  46.     02h     Minutes
  47.     03h     Minute Alarm
  48.     04h     Hours
  49.     05h     Hour Alarm
  50.     06h     Day of the Week
  51.     07h     Day of the Month
  52.     08h     Month
  53.     09h     Year
  54.     0Ah     Status Register A
  55.     0Bh     Status Register B
  56.     0Ch     Status Register C
  57.     0Dh     Status Register D
  58.     0Eh     Diagnostic Status Byte
  59.     0Fh     Shutdown Status Byte
  60.     10h     Disk Drive Type for Drives A: and B:
  61.         The drive-type bytes use bits 0:3 for the first
  62.         drive and 4:7 for the other
  63.         Disk drive types:
  64.         00h        no drive present
  65.         01h        double sided 360k
  66.         02h        high capacity (1.2 meg)
  67.         03h-0Fh     reserved
  68.     11h     (AT):Reserved     (PS/2):drive type for hard disk C:
  69.     12h     (PS/2):drive type for hard disk D:
  70.         (AT, XT/286):hard disk type for drives C: and D:
  71.         Format of drive-type entry for AT, XT/286:
  72.         0    number of cyls in drive (0-1023 allowed)
  73.         2    number of heads per drive (0-15 allowed)
  74.         3    starting reduced write compensation (not
  75.             used on AT)
  76.         5    starting cylinder for write compensation
  77.         7    max. ECC data burst length, XT only
  78.         8    control byte
  79.             Bit
  80.             7    disable disk-access retries
  81.             6    disable ECC retries
  82.             5-4  reserved, set to zero
  83.             3    more than 8 heads
  84.             2-0  drive option on XT (not used by AT)
  85.         9    timeout value for XT (not used by AT)
  86.            12    landing zone cylinder number
  87.            14    number of sectors per track (default 17,
  88.             0-17 allowed)
  89.     13h     Reserved
  90.     14h     Equipment Byte (corresponds to sw. 1 on PC and XT)
  91.     15h-16h    Base Memory Size      (low,high)
  92.     17h-18h    Expansion Memory Size (low,high)
  93.     19h-20h    Reserved
  94.         (PS/2) POS information Model 50 (60 and 80 use a 2k
  95.         CMOS RAM that is not accessible through software)
  96.     21h-2Dh    Reserved (not checksumed)
  97.     2Eh-2Fh    Checksum of Bytes 10 Through 20  (low,high)
  98.     30h-31h    Exp. Memory Size as Det. by POST (low,high)
  99.     32h     Date Century Byte
  100.     33h     Information Flags (set during power-on)
  101.     34h-3Fh    Reserved
  102.  3) The alarm function is used to drive the BIOS WAIT function
  103.     (int 15h function 90h).
  104.  4) To access the configuration RAM write the byte address (00-3Fh)
  105.     you need to access to I/O port 70h, then access the data via
  106.     I/O port 71h.
  107.  5) CMOS RAM chip is a Motorola 146818
  108.  6) The equipment byte is used to determine the configuration for
  109.     the POST power-on diagnostics.
  110.  7) Bytes 00-0Dh are defined by the chip for timing functions,
  111.     bytes 0Eh-3Fh  are defined by IBM.
  112.  8) Compaq 386 uses came CMOS chip as IBM AT. Extra functions:
  113.     byte 45 (2Dh) store additional info not maintained by AT
  114.     bit 0 indicates is Compaq dual-mode monitor isntalled
  115.     1 indicates whether keyclick is enabled
  116.     2 not used
  117.     3 if non-Compaq graphics adapter installed
  118.  
  119. Some CMOSes, (SXs) appear to store duplicates of registers 0..3F
  120. in 40..7F, others (DXs) store some other advanced configuration
  121. information in these registers.  Thus there are 64 byte and 128
  122. byte CMOSes.  We tell them apart by looking for a match in bytes
  123. in the checksum range.
  124.  
  125. Offsets 10..2F are included in the checksum.  We do not ever
  126. need to compute a checksum since we just save and restore.
  127.  
  128. Register Conventions
  129. ********************
  130.  
  131. Subroutines may trash all registers except those explicity
  132. documented as input or output.
  133.  
  134. | ; end of comment
  135.  
  136.  
  137. ;    E Q U A T E S
  138.  
  139. CMOSSAVE    EQU    1
  140. CMOSREST    EQU    2
  141. CMOSCHK     EQU    3
  142.  
  143. ; use /DGenerating#CMOSSAVE
  144. ;     /DGenerating#CMOSREST
  145. ;     /DGenerating#CMOSCHK
  146. ; on the assembler command line to select which version
  147. ; of the code to assemble.
  148. ;    Or add code following of the form:
  149.  
  150. GENERATING EQU CMOSSAVE
  151.  
  152.  
  153.     If    Generating eq CMOSSave
  154. %OUT Generating CMOSSave.Com
  155.     Endif
  156.  
  157.     If    Generating eq CMOSRest
  158. %OUT Generating CMOSRest.Com
  159.     endif
  160.  
  161.     If    Generating eq CMOSChk
  162. %OUT Generating CMOSChk.Com
  163.     endif
  164. ;==============================================================
  165.  
  166.  
  167. stack    segment stack        ; keep MS link happy by providing null stack
  168. stack    ends
  169.  
  170. CODE    SEGMENT PARA        ; start off in code.
  171.  
  172. ;==============================================================
  173.  
  174. data    segment byte        ; provide a separate DATA segment
  175.                 ; actually all come after the code
  176. ;==============================================================
  177. ;  V A R I A B L E S
  178.  
  179.  
  180.     If    Generating eq CMOSSave
  181.  
  182. BannerMsg    DB '░▒▓█ CMOSSave 1.1 █▓▒░',13d,10d
  183.         DB 13d,10d
  184.         DB 'Saves contents of CMOS to a file on hard disk or floppy.',13,10
  185.         DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
  186.         DB 'May be freely distributed and used for any purpose except military.',13,10
  187.         DB 13,10
  188.         db '$'
  189.  
  190. UsageMsg    DB '░▒▓█ Error █▓▒░',7,13,10
  191.         DB 'Insert a formatted diskette.',13,10
  192.         DB 'then try:',13,10
  193.         DB 'CMOSSav A:MyCMOS.Sav',13,10
  194.         DB 'or if wan to save on hard disk try:',13,10
  195.         DB 'CMOSSav C:\MyCMOS.Sav',13,10
  196.         DB 'Read CMOS.TXT to find how to use it properly.',13,10
  197.         db '$'
  198.  
  199. FileTroubleMsg    DB '░▒▓█ Error █▓▒░',7,13,10
  200.         DB 'Cannot create the disk file.',13,10
  201.         db '$'
  202.  
  203. WorkedMsg    DB 'CMOS successfully saved',13,10
  204.         db '$'
  205.  
  206.     EndIf
  207.  
  208.  
  209.     If    Generating eq CMOSRest
  210. BannerMsg    DB '░▒▓█ CMOSRest 1.1 █▓▒░',13d,10d
  211.         DB 13d,10d
  212.         DB 'Restores CMOS from a CMOSSave file on hard disk or floppy.',13,10
  213.         DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
  214.         DB 'May be freely distributed and used for any purpose except military.',13,10
  215.         DB 13,10
  216.         db '$'
  217.  
  218. UsageMsg    DB '░▒▓█ Error █▓▒░',13,10
  219.         DB 'Insert the diskette you used for CMOSSave.',13,10
  220.         DB 'then try:',13,10
  221.         DB 'CMOSRest A:MyCMOS.Sav',13,10
  222.         DB 'or if the file is on hard disk try:',13,10
  223.         DB 'CMOSRest C:\MyCMOS.Sav',13,10
  224.         DB 'Read CMOS.TXT to find how to use it properly.',13,10
  225.         db '$'
  226.  
  227. FileTroubleMsg    DB '░▒▓█ Error █▓▒░',7,13,10
  228.         DB 'Cannot find/read the disk file.',13,10
  229.         db '$'
  230.  
  231. WorkedMsg    DB 'CMOS successfully restored',13,10
  232.         db '$'
  233.  
  234.     EndIf
  235.  
  236.     If    Generating eq CMOSChk
  237. BannerMsg    DB '░▒▓█ CMOSChk 1.1 █▓▒░',13d,10d
  238.         DB 13d,10d
  239.         DB 'Ensures CMOS not corrupted or changed.',13,10
  240.         DB 'Copyright (c) 1991 Roedy Green Canadian Mind Products',13,10
  241.         DB 'May be freely distributed and used for any purpose except military.',13,10
  242.         DB 13,10
  243.         db '$'
  244.  
  245. UsageMsg    DB '░▒▓█ Error █▓▒░',7,13,10
  246.         DB 'Insert the diskette you used for CMOSSave.',13,10
  247.         DB 'then try:',13,10
  248.         DB 'CMOSChk A:MyCMOS.Sav',13,10
  249.         DB 'or if you have the file on hard disk try:',13,10
  250.         DB 'CMOSChk C:\MyCMOS.Sav',13,10
  251.         DB 'Read CMOS.TXT to find how to use it properly.',13,10
  252.         db '$'
  253.  
  254. FileTroubleMsg    DB '░▒▓█ Error █▓▒░',7,13,10
  255.         DB 'Cannot find/read the disk file.',13,10
  256.         db '$'
  257.  
  258. MatchTroubleMsg DB '░▒▓█ Error █▓▒░',7,13,10
  259.         DB 'CMOS has been corrupted!',13,10
  260.         db '$'
  261.  
  262. WorkedMsg    DB 'CMOS is OK, i.e. unchanged since the last CMOSSave.',13,10
  263.         db '$'
  264.  
  265.     EndIf
  266.  
  267.  
  268. FilenamePtr    DW    0
  269.             ; pointer to filename in command line
  270.  
  271. CMOSSize    DB    0
  272.             ; size of cmos in bytes
  273.  
  274. CMOSBuff    db 0    ; dynamic buffer will grow to 128
  275.             ; it hangs out past the end of the program
  276.  
  277. data        ends
  278.  
  279. com    group    code,data    ; force data segment to go at the end
  280.  
  281.     ASSUME    CS:com,DS:com,ES:com,SS:com
  282.                 ; seg regs cover everything
  283.     ORG    100H        ; in Code segment
  284.  
  285. ;==========================
  286.  
  287. Main    proc    far
  288.  
  289. ;    M A I N L I N E   R O U T I N E
  290. Start:
  291.     lea    dx,BannerMsg    ; display the banner
  292.     Call    Say
  293.     Call    Parse        ; get filename from command line
  294.  
  295.     If    Generating eq CMOSSave
  296.     call    GetCMOS     ; fetch CMOS to buffer
  297.     call    WriteCMOS    ; write CMOS contents to file
  298.     EndIf
  299.  
  300.     If    Generating eq CMOSRest
  301.     call    ReadCMOS    ; read CMOS contents from file
  302.     call    CalcCMOSSize    ; it is 64 or 128 bytes long?
  303.     call    PutCMOS     ; store buffer to CMOS
  304.     EndIf
  305.  
  306.     If    Generating eq CMOSChk
  307.     call    ReadCMOS    ; read CMOS contents from file
  308.     call    CalcCMOSSize    ; it is 64 or 128 bytes long?
  309.     call    CompareCMOS    ; compare CMOS with buffer
  310.     EndIf
  311.  
  312.     lea    dx,WorkedMsg    ; crow about success
  313.     Call    Say
  314. Done:
  315.     mov    ax,4c00h
  316.     int    21h        ;normal termination
  317.  
  318. Main    EndP
  319.  
  320. ;===============================================================
  321.  
  322. Trouble proc    near
  323.  
  324. FileTrouble:
  325.     Lea    dx,FileTroubleMsg    ; display file trouble
  326.     Call    Say
  327.     Jmp    Abort
  328.  
  329. abort:
  330.                 ; error exit
  331.     mov    ax, 4c04h    ; ERRORLEVEL = 4
  332.     int    21h        ; DIE
  333.  
  334. Trouble endp
  335.  
  336. ;===============================================================
  337.  
  338. MLeading    PROC    Near
  339.  
  340. ;    Remove leading blanks
  341. ;    on entry BX is addr of string, CX its length
  342. ;    trims off any leading blanks, leaving result in BX CX
  343. ;    length may also be 0 or 1, but not -ve
  344. ;    If the entire string is blank the result is the null string
  345.     mov    di,bx
  346.     mov    al,20H        ; AL = blank  -- the search char
  347.     jcxz    mleading2    ; jump if null string
  348.     repe    scasb        ; scan ES:DI forwards till hit non blank
  349.                 ; DI points just after it (wrap ok)
  350.                 ; cx IS ONE TOO SMALL, OR 0 IF NONE FOUND
  351.     je    mleading1    ; jump if entire string was blank
  352.     inc    cx        ; CX is length of remainder of string
  353. mleading1:
  354.     dec    di        ; DI points to non-blank
  355. mleading2:
  356.     mov    bx,di        ; put address back
  357.     ret
  358.  
  359. MLeading    ENDP
  360.  
  361. ;========================================
  362.  
  363. MTrailing    PROC    Near
  364.  
  365. ;    Remove trailing blanks.
  366. ;    on entry BX is addr of string, CX its length
  367. ;    trims off any trailing blanks, leaving result in BX CX
  368. ;    length may also be 0 or 1, but not -ve
  369. ;    If the entire string is blank the result is the null string
  370.     mov    di,bx
  371.     add    di,cx        ; calc addr last char in string
  372.     dec    di
  373.     mov    al,20H        ; AL = blank  -- the search char
  374.     jcxz    mtrailing1    ; jump if null string
  375.     std
  376.     repe    scasb        ; scan ES:DI backwards till hit non blank
  377.                 ; DI points just ahead of it (wrap ok)
  378.                 ; CX is one too small, or 0 if none found
  379.     cld
  380.     je    mtrailing1    ; jump if whole string was blank
  381.     inc    cx
  382. mtrailing1:
  383.     ret
  384.  
  385. MTrailing    ENDP
  386.  
  387. ;========================================
  388.  
  389. Parse        PROC    NEAR
  390. ;    Parse the command line to remove lead/trail blanks from
  391. ;    the single drive parameter and terminate it by 2 nulls.
  392. ;    sample inputs
  393. ;    CMOSRest A:\MyCMOS.SAV
  394. ;    CMOSRest    B:\MySub\MyCMOS.SAV
  395. ;
  396. ;    When Done DS:BX points to start of string.
  397. ;    String will be terminated by 2 nulls
  398. ;    CX counts bytes in string exclusive of nulls
  399.                 ; counted string at HEX 80 PSP
  400.                 ; contains command line.
  401.                 ; Preceeded by unwanted spaces.
  402.                 ; possibly followed by unwanted spaces.
  403.                 ; currently missing a trailing null.
  404.     xor    ch,ch
  405.     mov    cl,ds:80H
  406.     mov    bx,81H
  407.     call    Mleading    ; get rid of leading blanks
  408.     call    MTrailing    ; get rid of trailing blanks
  409.     mov    di,bx        ; calc addr of byte just past end
  410.     add    di,cx
  411.     mov    word ptr [di],0 ; plop in pair of nulls after string
  412.     mov    FileNamePtr,bx    ; remember where filename was
  413.     jcxz    SyntaxTrouble    ; missing parm.
  414.     ret
  415.  
  416. SyntaxTrouble:
  417.     lea    dx,UsageMsg        ; display usage message
  418.     Call    Say
  419.     Jmp    Abort
  420.  
  421. Parse        ENDP
  422.  
  423. ;======================================
  424.  
  425. Say    Proc
  426.  
  427. ;    on entry DX points to a string to display
  428.  
  429.     MOV    AH,9
  430.     Int    21h
  431.     ret
  432.  
  433. Say    EndP
  434.  
  435. ;======================================
  436.  
  437.     If    Generating eq CMOSSave
  438.  
  439. GetCMOS Proc    Near
  440.  
  441. ;    Get 128 byte contents of CMOS into a buffer.
  442.  
  443.     mov    cx,128        ; count of times through loop
  444.     lea    bx,CMOSBuff    ; where to put the contents
  445.     sub    al,al        ; start offset in CMOS
  446. GetLoop:
  447.     Call    PeekCmos    ; al=offset ah=contents
  448.     mov    byte ptr[bx],ah
  449.     inc    al
  450.     inc    bx
  451.     loop    GetLoop
  452.     ret
  453.  
  454. GetCMOS EndP
  455.  
  456.     EndIf
  457.  
  458. ;===============================================================
  459.  
  460.     If    Generating eq CMOSRest
  461.  
  462. PutCMOS Proc    Near
  463.  
  464. ;    Put 128-byte contents of buffer into CMOS.
  465. ;    do not touch the volatile bytes
  466.  
  467.     mov    cx,128        ; count of times through loop
  468.     lea    bx,CMOSBuff    ; where to put the contents
  469.     sub    al,al        ; start offset in CMOS
  470. PutLoop:
  471.     call    Volatile    ; test if this is a volatile byte
  472.                 ; test offset in al
  473.     jc    LeaveItAlone
  474.     mov    ah,byte ptr[bx]
  475.     Call    PokeCMOS    ; al=offset ah=contents
  476.  
  477. LeaveItAlone:
  478.     inc    bx
  479.     inc    al
  480.     loop    PutLoop
  481.     ret
  482.  
  483. PutCMOS EndP
  484.  
  485.     EndIf
  486.  
  487. ;===============================================================
  488.  
  489.     If    Generating eq CMOSChk
  490.  
  491. CompareCMOS    proc    Near
  492.  
  493. ;    compares buffer version of CMOS with contents of actual CMOS
  494. ;    ignores mismatches of volatile bytes.
  495. ;    Aborts if finds a mismatch
  496.  
  497.     mov    cx,128        ; count of times through loop
  498.     lea    bx,CMOSBuff    ; where to find comparison set
  499.     sub    al,al        ; start offset in CMOS
  500. CompLoop:
  501.     call    Volatile    ; test if this is a volatile byte
  502.                 ; test offset in al
  503.     jc    IgnoreMismatch
  504.     Call    PeekCMOS    ; al=offset ah=contents
  505.     cmp    ah,byte ptr[bx] ; compare CMOS with buffer
  506.     jne    MatchTrouble
  507.  
  508. IgnoreMismatch:
  509.     inc    bx
  510.     inc    al
  511.     loop    CompLoop
  512.     ret
  513.  
  514. MatchTrouble:
  515.     lea    dx,MatchTroubleMsg    ; display CMOS mismatch
  516.     call    Say
  517.     mov    ax, 4c01h        ; ERRORLEVEL = 1
  518.     int    21h            ; DIE
  519.  
  520. CompareCMOS    EndP
  521.  
  522.     EndIf
  523.  
  524. ;===============================================================
  525.  
  526.     If    Generating ne CMOSSave
  527.  
  528. Volatile    Proc    near
  529.  
  530. ;    Is cmos offset in AL volatile?    If so set carry.
  531. ;    These bytes will be undisturbed.
  532. ;    Preserves all registers.
  533. ;    00..0F and 32 are volatile, rest are not.
  534. ;    if cmos is small, all bytes past end are considered volatile
  535.  
  536.     cmp    al,CMOSSize        ; bytes past end are volatile
  537.     jae    IsVolatile
  538.     cmp    al,0fh
  539.     jbe    IsVolatile        ; early bytes are for timing
  540.     cmp    al,32h            ; 32 is date century byte,
  541.     je    IsVolatile        ; not exactly volatile, but ...
  542.  
  543. IsNotVolatile:
  544.     clc                ; clear carry
  545.     ret
  546.  
  547. IsVolatile:
  548.     stc
  549.     ret
  550.  
  551. Volatile    EndP
  552.     EndIf
  553.  
  554. ;===============================================================
  555.  
  556.     If    Generating ne CMOSSave
  557.  
  558. CalcCMOSSize    Proc    near
  559.  
  560. ;    Is CMOS 64 or 128 bytes long?
  561. ;    It is 64 if bytes at 10..2F match those at 50..6F.
  562. ;    Otherwise it is 128 bytes.
  563. ;    Preserves all registers.
  564.  
  565.     push    si
  566.     push    di
  567.     push    cx
  568.     lea    si,CMOSBuff+10h
  569.     lea    di,CMOSBuff+50h
  570.     mov    cx,02fh+1-10h
  571.     repe    cmpsb
  572.     je    IsCMOS64
  573.  
  574. IsCMOS128:
  575.     mov    CMOSSize,128    ; differ, must be a big CMOS
  576.     jmp    CalcCMOSSizeDone
  577.  
  578. IsCMOS64:
  579.     mov    CMOSSize,64    ; all same, small CMOS
  580.  
  581. CalcCMOSSizeDone:
  582.     pop    cx
  583.     pop    di
  584.     pop    si
  585.  
  586.     ret
  587.  
  588. CalcCMOSSize    EndP
  589.     EndIf
  590.  
  591. ;===============================================================
  592.  
  593.     if    Generating ne CMOSRest
  594.  
  595. PeekCMOS    proc    near
  596.  
  597. ;    Reads one byte from cmos.
  598. ;    on entry al has offset desired
  599. ;    on exit ah has the contents of that byte.
  600. ;    preserves all registers
  601.  
  602. ;    See page 5-81 IBM AT Tech ref BIOS listing for how to read CMOS
  603. ;    We always enable the NMI with bit 7 on.
  604.  
  605.     push    bx
  606.     push    ax
  607.     cli                ; disable interrupts
  608.     or    al,80h            ; disable NMI
  609.     out    70h,al            ; output the byte address to CMOS
  610.     jmp    $+2            ; delay, safer than nop
  611.     in    al,71h            ; read the CMOS byte
  612.     jmp    $+2            ; delay, safer than nop
  613.     mov    bl,al
  614.                     ; re-enable the NMI
  615.     mov    al,0dh            ; point to battery status register
  616.     out    70h,al            ; leave pointing at a safe r/o register
  617.     sti                ; restore interrupts
  618.     pop    ax
  619.     mov    ah,bl
  620.     pop    bx
  621.     ret
  622.  
  623. PeekCMOS    EndP
  624.  
  625.     EndIf
  626.  
  627. ;===============================================================
  628.  
  629.     If    Generating eq CMOSRest
  630.  
  631. PokeCMOS    proc    near
  632.  
  633. ;    Stuffs one byte into cmos.
  634. ;    on entry al has offset desired, ah has the value to stuff.
  635. ;    Preserves all registers.
  636.  
  637. ;    See page 5-81 IBM AT Tech ref BIOS listing for how to write CMOS
  638. ;    We always enable the NMI with bit 7 on.
  639.  
  640.     push    ax
  641.     cli                ; disable interrupts
  642.     or    al,80h            ; disable NMI
  643.     out    70h,al            ; output the byte address to CMOS
  644.     jmp    $+2            ; delay, safer than nop
  645.  
  646.     mov    al,ah            ; get contents
  647.     out    71h,al            ; poke the CMOS byte
  648.     jmp    $+2            ; delay, safer than nop
  649.                     ; re-enable the NMI
  650.     mov    al,0dh            ; point to battery status register
  651.     out    70h,al            ; leave pointing at a safe r/o register
  652.     sti                ; restore interrupts
  653.     pop    ax
  654.     ret
  655.  
  656. PokeCMOS    EndP
  657.  
  658.     EndIf
  659.  
  660. ;===============================================================
  661.  
  662.     If    Generating ne CMOSSave
  663.  
  664. ReadCMOS    Proc    Near
  665.  
  666. ;    Open a file read the CMOS into a buffer
  667.  
  668.     mov    dx,FileNamePtr    ; DS:DX point to file
  669.     xor    al,al        ; AL=0 is attribute read/only
  670.     mov    ah,03Dh     ; DOS open function
  671.     int    21h
  672.     jc    FileTrouble
  673.     mov    bx,ax        ; save handle
  674.     mov    cx,128        ; read 128 bytes
  675.     lea    dx,CMOSBuff    ; buffer address
  676.     mov    ah,3fH        ; DOS read
  677.     int    21h
  678.     jc    FileTrouble
  679.     cmp    ax,128
  680.     jne    FileTrouble
  681.     mov    ah,3eh        ; DOS close
  682.     int    21h
  683.     jc    FileTrouble
  684.     ret
  685.  
  686. ReadCMOS    EndP
  687.  
  688.     EndIf
  689.  
  690. ;===============================================================
  691.  
  692.     if    Generating eq CMOSSave
  693.  
  694. WriteCMOS    Proc    Near
  695.  
  696. ;    Create a file write CMOS to it
  697.  
  698.     mov    dx,FileNamePtr    ; DS:DX point to file
  699.     xor    cx,cx        ; CX=0 is attribute
  700.     mov    ah,03ch     ; DOS create function
  701.     int    21h
  702.     jc    FileTrouble
  703.     mov    bx,ax        ; SAVE HANDLE
  704.     MOV    CX,128        ; write 128 bytes
  705.     lea    dx,CMOSBuff    ; buffer address
  706.     mov    ah,40h        ; DOS write
  707.     int    21h
  708.     jc    FileTrouble
  709.     cmp    ax,128
  710.     jne    FileTrouble
  711.     mov    ah,3eh        ; DOS close
  712.     int    21h
  713.     jc    FileTrouble
  714.     ret
  715.  
  716. WriteCMOS    EndP
  717.  
  718.     EndIf
  719.  
  720. ;===============================================================
  721.  
  722. CODE    ends            ; end of code segment
  723.     end    Start
  724.